package com.lebang.configuration.redis;

import com.lebang.component.RedisClient;
import com.lebang.component.RedisSdkClient;
import com.lebang.domain.DownloadMemberRecord;
import com.lebang.entity.member.LbbMemberRecord;
import com.lebang.entity.task.LbbCommon;
import com.lebang.entity.task.LbbSosoWithBLOBs;
import com.lebang.entity.task.TaskComments;
import com.lebang.mapper.LbbCommonMapper;
import com.lebang.mapper.LbbMemberRecordMapper;
import com.lebang.model.enums.Booleans;
import com.lebang.model.enums.buss.DownStatus;
import com.lebang.model.enums.buss.TaskCategory;
import com.lebang.model.enums.buss.TaskStatus;
import com.lebang.service.CpaService;
import com.lebang.service.DownAppService;
import com.lebang.service.DownloadMemberRecordService;
import com.lebang.service.TaskInRedisService;
import com.lebang.service.task.TaskService;
import com.lebangweb.common.TextUtil;
import com.lebangweb.common.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

import static com.lebang.controller.api.SdkUploadApi.EVENT_KEY;
import static com.lebang.controller.api.SdkUploadApi.ON_SDK_MEMBER_ALL;
import static com.lebang.model.RedisKey.NEW_HAND_TASK;


@Slf4j
@Component
public class RedisKeyExpirationListener implements MessageListener {
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private LbbMemberRecordMapper memberRecordMapper;
    @Autowired
    private LbbCommonMapper commonMapper;
    @Resource(name = "commonTaskService")
    private TaskService<LbbCommon> commonTaskService;
    @Resource(name = "commentsTaskService")
    private TaskService<TaskComments> commentsTaskService;
    @Resource(name = "sosoTaskService")
    private TaskService<LbbSosoWithBLOBs> sosoTaskService;
    @Resource(name = "multiwordservice")
    private TaskService<LbbCommon> multiwordTaskService;
    @Autowired
    private RedisSdkClient sdkClient;

    @Autowired
    private CpaService cpaService;
    @Autowired
    private DownloadMemberRecordService downloadMemberRecordService;
    @Autowired
    private DownAppService downAppService;

    /**
     * 针对redis数据失效事件，进行数据处理
     *
     * @param message
     * @param patten
     */
    @Override
    public void onMessage(Message message, byte[] patten) {
        // 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
        String expiredKey = message.toString();
        // String topic = new String(patten, StandardCharsets.UTF_8);

        // redis 超时的事件
        if (expiredKey.startsWith(TaskInRedisService.getRecordTackPrefix())) {
            String taskId = expiredKey.replace(TaskInRedisService.getRecordTackPrefix(), "");
            // 任务超时释放任务
            releaseTask(taskId);
        }
        if (expiredKey.startsWith(EVENT_KEY)) {
            String json = expiredKey.replace(EVENT_KEY, "");
            sdkClient.lpush(ON_SDK_MEMBER_ALL, json);
        }
        if (expiredKey.startsWith(NEW_HAND_TASK)) {
            String json = expiredKey.replace(NEW_HAND_TASK, "");
            String uuid = UUIDUtil.L();
            boolean lock = redisClient.tryGetDistributedLock("locknewhandtask:" + json, uuid, 30000);
            if (lock) {
                List<String> id = new ArrayList<>(1);
                id.add(json);
                commonTaskService.examineAndVerify(id, "", "任务成功", "",1);
            } else {
                log.info("其他系统执行");
            }

        }
        if (expiredKey.startsWith(cpaService.getExpireKey())) {
            String id = expiredKey.replace(cpaService.getExpireKey(), "");
            String uuid = UUIDUtil.L();
            boolean lock = redisClient.tryGetDistributedLock("lockdownapp:" + id, uuid, 30000);
            if (lock) {
                DownloadMemberRecord record = downloadMemberRecordService.selectById(Long.valueOf(id));
                if (!record.getStatus().equals(DownStatus.WAIT_PUSH.getIndex())) {
                    return;
                }
                if (!TextUtil.isEmpty(record.getRouseDetailId())) {
                    cpaService.fail(record);
                } else {
                    downAppService.failBySys(record);
                }
            } else {
                log.info("其他系统执行");
            }

        }
        redisClient.del(expiredKey);


    }

    /**
     * 处理任务超时的任务
     *
     * @param taskId 释放任务
     */
    private void releaseTask(String taskId) {
        String pass = UUIDUtil.M();
        //对处理id增加分布式锁保证只有一个系统处理任务防止重复处理
        boolean lock = redisClient.tryGetDistributedLock("lockrecordid:" + taskId, pass, 30000);
        if (lock) {
            //注入service
            LbbMemberRecord record = memberRecordMapper.selectByid(Integer.parseInt(taskId), Booleans.False.name(), null);
            if (record == null) {
                log.info("该任务已被释放d:" + taskId);
                return;
            }
            int i = memberRecordMapper.deleteByid(record.getId());
            if (i == 0) {
                log.info("该任务已被释放d:" + taskId);
                return;
            }

            if (record.getRedo()>0) {
                record.setStatus(TaskStatus.CheckFailure);
                record.setRemark("任务超时未提交!");
                memberRecordMapper.updateByPrimaryKeySelective(record);
                log.info("重做的任务被释放直接审核失败:" + taskId);
                return;
            }
            if (record.getCategory().equals(TaskCategory.Common)) {
                LbbCommon task = commonMapper.getByTaskId(record.getTaskId());
                if (task.getIsMultiword() == 1) {
                    multiwordTaskService.releaseTask(record);
                } else {
                    // 释放任务
                    commonTaskService.releaseTask(record);
                }
            } else if (record.getCategory().equals(TaskCategory.Soso)) {
                sosoTaskService.releaseTask(record);
            } else if (record.getCategory().equals(TaskCategory.Comments)) {
                commentsTaskService.releaseTask(record);
            }
            log.info("任务释放成功:" + taskId);
            redisClient.releaseDistributedLock("lockrecordid:" + taskId, pass);
        } else {
            log.info("任务已在其他系统处理:" + taskId);
        }
    }


}